class Room:
    name = ""
    numOfSeats = 0

    def __init__(self, name, seats):
        self.name = name
        self.numOfSeats = seats

class Person:
    smoker = False
    manyVisitors = False
    status = 0
    room = None

    def __init__(self, smoking, visitors, status ):
        self.smoker = smoking
        self.manyVisitors = visitors
        self.status = status

class ConstraintSatisfactionProblem:
    Persons = []
    Rooms = []
    Constraints = []

    def __init__(self):
        self.Persons = []
        self.Rooms = []
        self.Constraints = [ ]

    

    def HighStatusInLargeOffice( self, assignment ):
        violated = False
        # Checking each assignment in assignment dict
        for k in assignment:
            if k.status < 3:
                if assignment[k].name < 2:
                    violated = True
        return violated
        # Checking only the first assignment in dict. Also has to remove it from assignment, should use a copy of the dict instead.
        #if assignment.keys().pop().status < 3 :
        #    if assignment.values().pop().numOfSeats < 2:
        #        violated = True
        #return violated

    def HeadAndProfessor( self, assignment ):
        violated = False



        # Old Version.
        #for person in persons:
        #    if person1.room == person.room:
        #        violated = True
        return violated

    def NonSmokerAndSmoker( self, person1, person2 ):
        violated = False
        if person1.room == person2.room:
            if person1.smoker:
                if not person2.smoker:
                    violated = True
            elif person2.smoker:
                if not person1.smoker:
                    violated = True
        return violated

    def ManyVisitorsAndFewVisitors( self, person1, person2 ):
        violated = False
        if person1.room == person2.room:
            if person1.manyVisitors:
                if person2.manyVisitors:
                    violated = True
        return violated

    def LoadConstraints( self ):
        self.Constraints.append( self.HighStatusInLargeOffice )



# def RecursiveBacktracking( {}, csp ):
# if assignment is complete then return assignment
# var <- select-unassigned-variable( variables[csp], assignment, csp)
# for each value in Order-Domain-Values(var,assignment,csp) do
#   if value is consistent with assignment according to Constraints[csp] then
#       add {var = value} to assignment
#       result <- RecursiveBacktracking(assignment,csp)
#       if result != failure then return result
#       remove {var = value} from assignment
#   return failure




########### MAIN: ############

csp = ConstraintSatisfactionProblem()




csp.Rooms.append( Room('T13', 1) )
csp.Rooms.append( Room('T14', 1) )
csp.Rooms.append( Room('T15', 1) )
csp.Rooms.append( Room('T16', 1) )
csp.Rooms.append( Room('T11', 2) )
csp.Rooms.append( Room('T12', 2) )
csp.Rooms.append( Room('T10', 3) )

csp.Persons.append( Person(False, True, 1) )
csp.Persons.append( Person(False, True, 2) )
#csp.Persons.append( Person(False, False, 2) )
#csp.Persons.append( Person(True, True, 2) )
#csp.Persons.append( Person(True, True, 3) )
#csp.Persons.append( Person(False, False, 3) )
#csp.Persons.append( Person(False, False, 3) )
#csp.Persons.append( Person(False, True, 4) )
#csp.Persons.append( Person(True, False, 4) )
#csp.Persons.append( Person(True, False, 4) )
#csp.Persons.append( Person(False, False, 4) )

assignment = {}

assignment[csp.Persons[0]] = csp.Rooms[0]

csp.LoadConstraints()

for func in csp.Constraints:
    if func( assignment ):
        print(func, "Returned true" )
    else:
        print( func, "Returned False" )

